package com.bsj.media.media.h26X;


import com.bsj.media.media.gb28181.decodeSPS;

/**
 * @Description h264的sps(序列参数集)帧信息,具体说明:https://www.xjx100.cn/news/375863.html?action=onClick
 * @Date 2023/10/26 11:19
 **/
public class H264NaluSPSInfo {
    int profile_idc; // 标识当前H264码流的profile
    int level_idc; // 标识当前码流的Level
    int seq_parameter_set_id; // 表示当前的序列参数集的id。通过该id值，图像参数集pps可以引用其代表的sps中的参数。
    int log2_max_frame_num_minus4; // 用于计算MaxFrameNum的值
    int pic_order_cnt_type; // 表示解码picture order count(POC)的方法
    int log2_max_pic_order_cnt_lsb_minus4; // 用于计算MaxPicOrderCntLsb的值
    int max_num_ref_frames; // 用于表示参考帧的最大数目。
    int gaps_in_frame_num_value_allowed_flag; // 标识位，说明frame_num中是否允许不连续的值。
    int pic_width_in_mbs_minus1; // 用于计算图像的宽度。单位为宏块个数，因此图像的实际宽度为:
    int pic_height_in_map_units_minus1; // 使用PicHeightInMapUnits来度量视频中一帧图像的高度
    int frame_mbs_only_flag;  // 标识位，说明宏块的编码方式。当该标识位为0时，宏块可能为帧编码或场编码；该标识位为1时，所有宏块都采用帧编码
    /**
     * 解析sps帧的详细信息
     * @param sps: 去除00 00 00 01的sps帧信息
     * @return
     **/
    public static H264NaluSPSInfo analysisNaluSPSInfo(byte[] sps) {
        H264NaluSPSInfo info = new H264NaluSPSInfo();
        int[] startBit = new int[1];
        decodeSPS.de_emulation_prevention(sps, new int[]{sps.length});
        int forbidden_zero_bit = decodeSPS.u(1, sps, startBit);
        int nal_ref_idc = decodeSPS.u(2, sps, startBit);
        int nal_unit_type = decodeSPS.u(5, sps, startBit); // NALU单元的类型，7表示SPS帧
        if (nal_unit_type == 7) {
            info.profile_idc = decodeSPS.u(8, sps, startBit);
            int constraint_set0_flag = decodeSPS.u(1, sps, startBit);// (buf[1] & 0x80)>>7;
            int constraint_set1_flag = decodeSPS.u(1, sps, startBit);// (buf[1] & 0x40)>>6;
            int constraint_set2_flag = decodeSPS.u(1, sps, startBit);// (buf[1] & 0x20)>>5;
            int constraint_set3_flag = decodeSPS.u(1, sps, startBit);// (buf[1] & 0x10)>>4;
            int reserved_zero_4bits = decodeSPS.u(4, sps, startBit);
            info.level_idc = decodeSPS.u(8, sps, startBit);
            info.seq_parameter_set_id = decodeSPS.Ue(sps, sps.length, startBit);

            if (info.profile_idc == 100 || info.profile_idc == 110 || info.profile_idc == 122 || info.profile_idc == 244
                    || info.profile_idc == 44|| info.profile_idc == 83|| info.profile_idc == 86|| info.profile_idc == 118|| info.profile_idc == 128) {
                int chroma_format_idc = decodeSPS.Ue(sps, sps.length, startBit);
                if (chroma_format_idc == 3) {
                    int residual_colour_transform_flag = decodeSPS.u(1, sps, startBit);
                }
                int bit_depth_luma_minus8 = decodeSPS.Ue(sps, sps.length, startBit);
                int bit_depth_chroma_minus8 = decodeSPS.Ue(sps, sps.length, startBit);
                int qpprime_y_zero_transform_bypass_flag = decodeSPS.u(1, sps, startBit);
                int seq_scaling_matrix_present_flag = decodeSPS.u(1, sps, startBit);

                int[] seq_scaling_list_present_flag = new int[8];
                if (seq_scaling_matrix_present_flag != 0) {
                    for (int i = 0; i < 8; i++) {
                        seq_scaling_list_present_flag[i] = decodeSPS.u(1, sps, startBit);
                        // 新加begin
                        if (seq_scaling_list_present_flag[i] != 0) {
                            /* seq_scaling_list_present */
                            int last = 8, next = 8, size = (i < 6) ? 16 : 64;
                            for (int j = 0; j < size; j++) {

                                if (next != 0) {
                                    next = (last + decodeSPS.Se(sps, sps.length, startBit)) & 0xff;
                                }
                                last = next > 0 ? next : last;
                            }
                        }
                        // 新加end
                    }
                }
            }

            info.log2_max_frame_num_minus4 = decodeSPS.Ue(sps, sps.length, startBit);
            info.pic_order_cnt_type = decodeSPS.Ue(sps, sps.length, startBit);
            if (info.pic_order_cnt_type == 0) {
                info.log2_max_pic_order_cnt_lsb_minus4 = decodeSPS.Ue(sps, sps.length, startBit);
            } else if (info.pic_order_cnt_type == 1) {
                int delta_pic_order_always_zero_flag = decodeSPS.u(1, sps, startBit);
                int offset_for_non_ref_pic = decodeSPS.Se(sps, sps.length, startBit);
                int offset_for_top_to_bottom_field = decodeSPS.Se(sps, sps.length, startBit);
                int num_ref_frames_in_pic_order_cnt_cycle = decodeSPS.Ue(sps, sps.length, startBit);

                int[] offset_for_ref_frame = new int[num_ref_frames_in_pic_order_cnt_cycle];
                for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
                    offset_for_ref_frame[i] = decodeSPS.Se(sps, sps.length, startBit);
                }
            }
            info.max_num_ref_frames = decodeSPS.Ue(sps, sps.length, startBit);
            info.gaps_in_frame_num_value_allowed_flag = decodeSPS.u(1, sps, startBit);
            info.pic_width_in_mbs_minus1 = decodeSPS.Ue(sps, sps.length, startBit);
            info.pic_height_in_map_units_minus1 = decodeSPS.Ue(sps, sps.length, startBit);

            info.frame_mbs_only_flag = decodeSPS.u(1, sps, startBit);
            if (info.frame_mbs_only_flag == 0) {
                int mb_adaptive_frame_field_flag = decodeSPS.u(1, sps, startBit);;
            }
        }
        return info;
    }
}
